﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.Networking;

public enum Dir {
    UP = 0,
    RIGHT = 2,
    DOWN = 4,
    LEFT = 6
}

public class DogFu : MonoBehaviour
{
    
    [SerializeField]
    private Vector2 groundCheckVec;
    [SerializeField]
    private Transform groundCheck;
    [SerializeField]
    public Animator anim;
    [SerializeField]
    public float speed = 0.25f;
    
    [SerializeField]
    private float jumpForceValue = 1f;
    
    [SerializeField]
    private PhysicsMaterial2D friction0;
    [SerializeField]
    private PhysicsMaterial2D frictionMax;
    [SerializeField]
    private LayerMask whatIsGround;
    [SerializeField]
    private float slopeCheckDistance;
    


    
    public FSM fsm;


    private Rigidbody2D rb;
    private Vector2 newV;

    private BoxCollider2D cc;
    private Vector2 colliderSize; 

    private float slopeDownAngle;
    private float slopeHitNormalX;
    private float slopeDownAngleOld;
    private Vector2 slopeNormalPerp;//垂直于斜面法线的向量

    private bool isOnSlope;


    private Dir faceDir = Dir.LEFT;



    private void Awake() {

    }

//     IEnumerator Get()
//     {
//         string path;
//         //初始化配置
//         path = "file://" + Application.streamingAssetsPath + "/test.lua";
//         UnityWebRequest webRequest = UnityWebRequest.Get(path);
//         yield return webRequest.SendWebRequest();
//         //异常处理，很多博文用了error!=null这是错误的，请看下文其他属性部分
//         if (webRequest.isHttpError || webRequest.isNetworkError)
//             Debug.Log(webRequest.error);
//         else
//         {
            
//             RuiQuGame_EncryptFile luaDecode = new RuiQuGame_EncryptFile();

//             var bytes = webRequest.downloadHandler.data;
//             var newBytes = luaDecode.Decrypt(bytes, bytes.Length);
            
// string str = System.Text.Encoding.Default.GetString(newBytes);
// Debug.Log(str);
//         }
//     }


    /// 计算移动移动速度的方向（向量）
    private void CalculateMoveVelocityVec() {
        Vector2 checkPos = transform.position + new Vector3(cc.offset.x, cc.offset.y, 0);//new Vector3(0f, cc.size.y / 2);
        RaycastHit2D hit = Physics2D.Raycast(checkPos, Vector2.down, slopeCheckDistance, whatIsGround);
        if (hit) {
            slopeNormalPerp = Vector2.Perpendicular(hit.normal).normalized;
            slopeDownAngle = Vector2.Angle(hit.normal, Vector2.up);
            slopeHitNormalX = hit.normal.x;
            // Debug.Log("slopeDownAngle" + slopeDownAngle);

            // Debug.DrawRay(hit.point, slopeNormalPerp, Color.red);
            // Debug.DrawRay(hit.point, hit.normal,Color.green);
        }

    }

    private void SlopeCheckHorizontal(Vector2 checkPos) {

    }

    private void SlopeCheckVertical(Vector2 checkPos) {
        RaycastHit2D hit = Physics2D.Raycast(checkPos, Vector2.down, slopeCheckDistance, whatIsGround);
        if (hit) {
            slopeNormalPerp = Vector2.Perpendicular(hit.normal).normalized;
            slopeDownAngle = Vector2.Angle(hit.normal, Vector2.up);

            // if (slopeDownAngleOld != slopeDownAngle) {
            //     isOnSlope = true;
            // }

            // slopeDownAngleOld = slopeDownAngle;

            

            Debug.DrawRay(hit.point, slopeNormalPerp, Color.red);
            Debug.DrawRay(hit.point, hit.normal,Color.green);
        }
    }

    private void ApplyMovement() {
        
    }

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        cc = GetComponent<BoxCollider2D>();
        // colliderSize = cc.r;

        fsm = new FSM();
        var idle = new FSM.State("idle");
        idle.OnEnter = ()=>{
            anim.Play("FuFuStand0");
            Debug.Log("slopeDownAngle:" + slopeDownAngle);
            var angle = slopeDownAngle;
            if (slopeHitNormalX > 0) {
                angle = -slopeDownAngle;
            }
            if (Dir.LEFT == faceDir) {
                transform.eulerAngles = new Vector3(transform.eulerAngles.x,transform.eulerAngles.y,angle); 
            }
            else {
                transform.eulerAngles = new Vector3(transform.eulerAngles.x,transform.eulerAngles.y,-angle); 
            }


            if (slopeDownAngle > 60) {
                rb.sharedMaterial = friction0;
            }
            else {
                rb.sharedMaterial = frictionMax;
            }
        };

        idle.OnFixUpdate = ()=>{
            if (inputVelocity != Vector2.zero) {
                fsm.HandleEvent("idle2walk");
                rb.velocity = inputVelocity;
            }
        };

        var walk = new FSM.State("walk");
        walk.OnEnter = ()=>{
            anim.Play("FuFuWalk");
            rb.sharedMaterial = friction0;
        };
        walk.OnUpdate = ()=>{
            var angle = slopeDownAngle;
            if (slopeHitNormalX > 0) {
                angle = -slopeDownAngle;
            }
            if (Dir.LEFT == faceDir) {
                transform.eulerAngles = new Vector3(transform.eulerAngles.x,transform.eulerAngles.y,angle); 
            }
            else {
                transform.eulerAngles = new Vector3(transform.eulerAngles.x,transform.eulerAngles.y,-angle); 
            }
        };
        walk.OnFixUpdate = ()=>{
            if (inputVelocity == Vector2.zero) {
                fsm.HandleEvent("walk2idle");
            }
            rb.velocity = inputVelocity;
        };

        var run = new FSM.State("run");


        var air = new FSM.State("air");
        air.OnFixUpdate = ()=> {
            // 检查是否触地
            rb.velocity = new Vector2(inputVelocity.x, rb.velocity.y);

            var isCheckOverlapGround = Physics2D.OverlapBox(groundCheck.position, groundCheckVec,0, whatIsGround);
            if (isCheckOverlapGround) {
                //落地
                Debug.Log("落地啦！");
                if (inputVelocity == Vector2.zero) {
                    fsm.HandleEvent("air2idle");
                }
                else {
                    fsm.HandleEvent("air2walk");
                }
            }
        };

        var jumpUp = new FSM.State("jumpUp");
        jumpUp.OnEnter = ()=>{
            Jump();
        };
        jumpUp.OnFixUpdate = ()=>{
            if (rb.velocity.y < 0) {
                fsm.HandleEvent("jumpUp2air");
            }
            rb.velocity = new Vector2(inputVelocity.x, rb.velocity.y);
        };

        fsm.AddState(idle);
        fsm.AddState(walk);
        fsm.AddState(run);
        fsm.AddState(jumpUp);
        fsm.AddState(air);

        fsm.AddTranslation(new FSM.Tran(idle, walk, "idle2walk"));
        fsm.AddTranslation(new FSM.Tran(idle, air, "idle2air"));
        fsm.AddTranslation(new FSM.Tran(idle, run, "idle2run"));
        fsm.AddTranslation(new FSM.Tran(idle, jumpUp, "idle2jumpUp"));


        fsm.AddTranslation(new FSM.Tran(walk, idle, "walk2idle"));
        fsm.AddTranslation(new FSM.Tran(walk, run, "walk2run"));
        fsm.AddTranslation(new FSM.Tran(walk, air, "walk2air"));
        fsm.AddTranslation(new FSM.Tran(walk, jumpUp, "walk2jumpUp"));

        fsm.AddTranslation(new FSM.Tran(run, idle, "run2idle"));
        fsm.AddTranslation(new FSM.Tran(run, walk, "run2walk"));
        fsm.AddTranslation(new FSM.Tran(run, air, "run2air"));

        fsm.AddTranslation(new FSM.Tran(jumpUp, air, "jumpUp2air"));


        fsm.AddTranslation(new FSM.Tran(air, idle, "air2idle"));
        fsm.AddTranslation(new FSM.Tran(air, walk, "air2walk"));
        fsm.AddTranslation(new FSM.Tran(air, run, "air2run"));

        fsm.Start(air);
    }

    // Update is called once per frame
    void Update()
    {
        fsm.currState.DoUpdate();

        inputVelocity = Vector2.zero;
        if (Input.GetKey(KeyCode.A)) {
            inputVelocity += new Vector2(speed * slopeNormalPerp.x, speed * slopeNormalPerp.y);
            SetFace(Dir.LEFT);
        }
        if (Input.GetKey(KeyCode.D)) {
            inputVelocity += new Vector2(speed * -slopeNormalPerp.x, speed * -slopeNormalPerp.y);
            SetFace(Dir.RIGHT);
        }

        if (Input.GetKeyDown(KeyCode.Space)) {
            fsm.HandleEvent("idle2jumpUp");
            fsm.HandleEvent("walk2jumpUp");
            fsm.HandleEvent("run2jumpUp");
        }
    }

    /// 通过玩家输入的速度
    private Vector2 inputVelocity;
    private void FixedUpdate() {
        fsm.currState.DoFixUpdate();
        CalculateMoveVelocityVec();


        

    }

    private void Jump() {
        rb.velocity = Vector2.zero;
        Vector2 jumpForce = Vector2.zero;
        jumpForce.Set(0f, jumpForceValue);
        rb.AddForce(jumpForce, ForceMode2D.Impulse);
    }

    private void SetFace(Dir dir)
    {
        if (faceDir != dir) {
            transform.Rotate(0.0f, 180.0f, 0.0f);
            faceDir = dir;
        }
    }
    
    private void OnDrawGizmos()
    {
        // Gizmos.DrawWireCube(groundCheck.position, groundCheckVec);

    }
}